package com.googlecode.allinclusive.fw.core.data.input.excel.parser;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.core.io.Resource;

import com.googlecode.allinclusive.fw.core.converter.Converter;
import com.googlecode.allinclusive.fw.core.converter.ConverterRegistry;
import com.googlecode.allinclusive.fw.core.data.Form;
import com.googlecode.allinclusive.fw.core.data.input.DataParser;
import com.googlecode.allinclusive.fw.core.data.input.excel.config.ExcelConfig;
import com.googlecode.allinclusive.fw.core.data.mapping.MappingParser;

public abstract class ExcelParser extends DataParser {

	/** Excel映射配置*/
	Map<String, ExcelConfig> mappingConfigs;
	
	/**
	 * 构造方法
	 * @param mappingParser 数据映射文件解析器 
	 * @param mappingLocations 映射文件
	 */
	@SuppressWarnings("unchecked")
	public ExcelParser(MappingParser mappingParser, String[] mappingLocations) {
		mappingConfigs = (Map<String, ExcelConfig>) mappingParser.parse(mappingLocations);
	}
	
	/**
	 * 解析数据文件并生成DataForm对象
	 * @param formClass 数据文件类型（以Form的类名作为映射文件配置信息的标识ID）
	 * @param resources 数据文件 
	 * @param errorMaps 解析&验证失败错误信息
	 * @return DataForm对象
	 */
	@Override
	public List<Form> parse(Class<? extends Form> formClass, Resource[] resources, Map<String, Object> errorMaps) {
		// 数据文件 + 数据文件类型(映射文件) + 文件解析器(this)
		
		// 1. 根据formClass获取映射文件配置信息
		ExcelConfig excelConfig = mappingConfigs.get(formClass.getName());
		
		// 根据映射文件解析数据文件并生成DataForm对象
		List<Form> excelForms = new ArrayList<Form>();
		for (Resource resource : resources) {
			// 错误信息
			Collection<Object> errors = new ArrayList<Object>();
			errorMaps.put(resource.getDescription(), errors);
			
			// 解析数据文件
			excelForms.addAll(parse(formClass, excelConfig, resource, errors));
		}
		
		return excelForms;
	}
	
	/**
	 * 解析数据文件并生成Form对象
	 * @param excelConfig 映射文件配置信息
	 * @param resource 数据文件 
	 * @param errors 解析&验证失败错误信息
	 * @return Form对象
	 */
	public abstract List<Form> parse(Class<? extends Form> formClass, ExcelConfig excelConfig, Resource resource, final Collection<Object> errors);
	
	/**
	 * 创建Form对象
	 * @param formClass Form对象类型
	 * @return Form对象
	 */
	protected Form createForm(Class<? extends Form> formClass) {
		
		Form form = null;
		try {
			form = formClass.newInstance();
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
		return form;
	}
	
	/**
	 * 设置Form对象属性
	 * @param form Form对象
	 * @param propertyName 属性名
	 * @param cellValue 单元格内容
	 */
	protected void setProperty(final Form form, String propertyName, Object cellValue) {
		if (cellValue != null) {
			// Type Convert
			BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(form);
			Class propertyType = bw.getPropertyType(propertyName);
			// convert
			Converter converter = ConverterRegistry.lookup(propertyType);
			if (converter == null) {
				throw new RuntimeException("no converter found.");
			}
			Object propertyValue = converter.convert(cellValue);
			// set property value
			bw.setPropertyValue(propertyName, propertyValue);
		}
	}
}
